package back;

/**
 * Clase Tablero permite definir el comportamiento de un Tablero
 */

public class Tablero {

	private Celda[][] tablero;
	private int filas;
	private int cols;
	private Coordenada jugador;
	private int destinosRestantes=0;
	private int cajas=0;
	private int destinos=0;
	private boolean gameOver=false;
	/**
	 * Constructor de la clase Tablero
	 * @param int fil cantidad de filas del tablero
	 * @param int col cantidad de columnas del tablero
	 */
	public Tablero(int fil, int col) {
		validaTablero(fil, col);
		this.tablero = new Celda[fil][col];
		filas=fil;
		cols=col;
		inicializa();
				
	}
	
	/**
	 * Retorna la cantidad de filas del tablero
	 * @return int filas del tablero
	 */
	
	public int getFils(){
		return filas;
	}
	
	/**
	 * Retorna la cantidad de columnas del tablero
	 * @return int columnas del tablero
	 */
	
	public int getCols(){
		return cols;
	}
	
	/**
	 * Retorna la cantidad de destinos del nivel
	 * @return int destinos del nivel
	 */
	
	public int getDestinos(){
		return this.destinos;
	}
	
	
	/**
	 * Retorna la cantidad actual de cajas
	 * @return int cajas cantidad de cajas actuales
	 */
	
	public int getCajas(){
		return this.cajas;
	}
	
	/**
	 * Inicializa el Tablero lleandolo de vacios
	 */
	
	public void inicializa(){
		for(int i=0; i < (this.tablero).length; i++){
			for(int j=0; j< (this.tablero[0]).length; j++){
				Celda vacia=new Celda(i, j, this);
				vacia.setNoMovible(new Vacio());
				vacia.setMovible(new VacioM());
				this.tablero[i][j]= vacia;
			}
		}
	}
	
	/**
	 * Valida las dimensiones del tablero
	 * @param int fil filas del tablero
	 * @param int col columnas del tablero
	 * @throws IllegalArgumentException en caso de parametros invalidos
	 */
	
	private void validaTablero(int fil, int col) {
		if(fil < 5 || col < 5 || fil > 20 || col > 20) {
			throw new IllegalArgumentException();
		}
	}
	
	/**
	 * Valida que la Coordenada pasada como parametro
	 * pertenzca al tablero, y en ese caso devuelve verdadero
	 * @param Coordenada coord
	 * @return boolean
	 */
	
	private boolean validaCoord(Coordenada coord){
		return !(coord.getX()>= this.getFils() || coord.getY()>= this.getCols());
	}
	
	/**
	 * Retorna la Celda de la Coordenada pasada como parametro
	 * @param Coordenada coord
	 * @return Celda celda 
	 */
	
	public Celda getCelda(Coordenada coord){
		return tablero[coord.getX()][coord.getY()];
	}
	
	/**
	 * Setea en coord recibida la celda recibida como parametro
	 * @param Coordenada coor
	 * @param Celda celda
	 */
	
	public void SetCelda(Coordenada coord, Celda celda){
		tablero[coord.getX()][coord.getY()]=celda;
	}
	
	
	/**
	 * Realiza el movimiento en caso de que sea posible
	 * @param int direccion del movimiento
	 */
	
	public void posibleMovida(int direccion){
		Celda celdaActual=this.getJugador();
		if(celdaActual.posibleMovida(direccion) ){
			this.getJugador().getMovible().mueve(celdaActual, direccion);
			this.jugador=this.jugador.hacia(direccion);
		}
	}


	/**
	 * Retorna true si las cajas estan en los destinos correspondientes
	 * false en caso contrario
	 * @return boolean
	 */
	
	public boolean tableroTerminado(){
		if(this.destinosRestantes == 0){
			if(this.cajas == this.destinos){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Agrega celda en coord
	 * @param Object celda
	 * @param Coordenada coord
	 * @throws IllegalArgumentException si la coordenada fuera invalida
	 */
	
	public void agrega(Object celda, Coordenada coord) {
		
		if(validaCoord(coord) == false){
			throw new IllegalArgumentException();
		}
		
		this.getCelda(coord).agrega(celda, coord);
	}

	/**
	 * Retorna la cantidad de destinos restantes
	 * @return int destinosRestantes
	 */
	
	public int getDestinosRestantes() {
			return destinosRestantes;
	}
	
	/**
	 * Retorna la cantidad de movimientos realizados por el jugador
	 * @return int movimientos realizados por el jugador
	 */
	
	public int getMovimientos(){
		Jugador jug= (Jugador)this.getJugador().getMovible();
		return jug.getMovimientos();
	}
	
	/**
	 * Setea la cantidad de movimientos realizados por el jugador
	 * @param int mov nueva cantidad de movimientos. 
	 */
	
	public void setMovimientos(int mov){
		Jugador jug= (Jugador)this.getJugador().getMovible();
		jug.setMovimientos(mov);
	}
	
	/**
	 * Retorna true en caso de que el jugador haya sido movido hacia un agujero
	 * @return boolean
	 */
	public boolean perdido() {
		return gameOver;
	}

	/**
	 * Decrementa la variable cajas en el tablero
	 */
	
	public void eliminaCaja() {
		this.cajas--;
	}
	
	/**
	 * Incrementa la variable cajas en el tablero
	 */
	
	public void agregaCaja() {
		this.cajas++;
		
	}
	
	/**
	 * Decrementa la variable destinosRestantes en el tablero
	 */
	
	public void eliminaDestinosRest(){
		this.destinosRestantes--;
	}
	
	/**
	 * Incrementa la variable destinosRestantes en el tablero
	 */
	
	public void agregaDestinosRest(){
		this.destinosRestantes++;
	}
	
	/**
	 * Incrementa las variables destinos y destinosRestantes en el tablero
	 */
	
	public void agregaDestinos(){
		this.destinos++;
		this.destinosRestantes++;
	}
	
	/**
	 * Setea a gameOver en true
	 */
	
	public void gameOver(){
		this.gameOver=true;
	}
	
	/**
	 * Setea la coordenada del jugador
	 * @param Coordenada coord nueva coordenada del jugador
	 */
	
	public void setJugador(Coordenada coord){
		 this.jugador=coord;
	}
	
	/**
	 * Retorna la celda en donde esta el jugador
	 * @return Celda en donde esta el jugador
	 */
	
	public Celda getJugador(){
		return this.getCelda(this.jugador);
	}
	 		
}